package org.dromara.web.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.secure.BCrypt;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.dromara.basic.service.IDictService;
import org.dromara.common.core.constant.UserConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.domain.model.LoginBody;
import org.dromara.common.core.domain.model.RegisterBody;
import org.dromara.common.core.domain.model.SmsLoginBody;
import org.dromara.common.core.domain.model.SocialLoginBody;
import org.dromara.common.core.utils.*;
import org.dromara.common.encrypt.annotation.ApiEncrypt;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.common.social.config.properties.SocialLoginConfigProperties;
import org.dromara.common.social.config.properties.SocialProperties;
import org.dromara.common.social.utils.SocialUtils;
import org.dromara.common.tenant.helper.TenantHelper;
import org.dromara.common.websocket.utils.WebSocketUtils;
import org.dromara.device.domain.bo.SendToServer;
import org.dromara.run.service.IDeptService;
import org.dromara.system.domain.*;
import org.dromara.system.domain.bo.SysSocialUserBo;
import org.dromara.system.domain.bo.SysTenantBo;
import org.dromara.system.domain.bo.SysUserBo;
import org.dromara.system.domain.vo.SysSocialUserVo;
import org.dromara.system.domain.vo.SysTenantVo;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.mapper.*;
import org.dromara.system.service.*;
import org.dromara.utils.service.SynchronizeImageService;
import org.dromara.web.domain.vo.LoginTenantVo;
import org.dromara.web.domain.vo.LoginVo;
import org.dromara.web.domain.vo.TenantListVo;
import org.dromara.web.service.IAuthStrategy;
import org.dromara.web.service.SysLoginService;
import org.dromara.web.service.SysRegisterService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.net.URL;
import java.util.List;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 认证
 *
 * @author Lion Li
 */
@Slf4j
@SaIgnore
@RequiredArgsConstructor
@RestController
@RequestMapping("/openapi/auth")
public class OpenAuthController {

    private final SysLoginService loginService;
    private final ISysClientService clientService;
    private final ScheduledExecutorService scheduledExecutorService;
    private final SynchronizeImageService synchronizeImageService;
    @Autowired
    private ISysSocialUserService sysSocialUserService;
    private final SysSocialUserMapper sysSocialUserMapper;
    private final SysUserMapper  userMapper;
    private final SysDictDataMapper sysDictDataMapper;
    private final ISysConfigService configService;
    private final SysUserRoleMapper userRoleMapper;
    private final SysRoleMapper sysRoleMapper;
    @PostMapping("/login")
    public R<LoginVo> loginForLs(@RequestBody String body) {
        LoginBody loginBody = JsonUtils.parseObject(body, LoginBody.class);
        loginBody.setClientId("e5cd7e4891bf95d1d19206ce24a7b32e");
        loginBody.setTenantId("000000");
        loginBody.setClientKey("pc");
        loginBody.setGrantType("password");
//        ValidatorUtils.validate(loginBody);
        // 授权类型和客户端id
        String clientId = loginBody.getClientId();
        String grantType = loginBody.getGrantType();
        SysClient client = clientService.queryByClientId(clientId);
        // 查询不到 client 或 client 内不包含 grantType
        if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) {
            log.info("客户端id: {} 认证类型：{} 异常!.", clientId, grantType);
            return R.fail(MessageUtils.message("auth.grant.type.error"));
        } else if (!UserConstants.NORMAL.equals(client.getStatus())) {
            return R.fail(MessageUtils.message("auth.grant.type.blocked"));
        }
        if(StringUtils.isNotEmpty(loginBody.getTenantId())){
            // 校验租户
            loginService.checkTenant(loginBody.getTenantId());
        }else {
            SmsLoginBody smsLoginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
            SysUserVo sysUserVo = loginService.selectUserByPhonenumber(smsLoginBody.getPhonenumber());
            if(sysUserVo!=null){
                smsLoginBody.setTenantId(sysUserVo.getTenantId());
                body= JsonUtils.toJsonString(smsLoginBody);
            }else {
                return R.fail("手机号码无效，请用账号密码登录");
            }
        }

        // 登录
        LoginVo loginVo = IAuthStrategy.login(body, client, grantType);

        Long userId = LoginHelper.getUserId();

        scheduledExecutorService.schedule(() -> {
            WebSocketUtils.sendMessage(userId, "欢迎登录RuoYi-Vue-Plus后台管理系统");
        }, 3, TimeUnit.SECONDS);
        return R.ok(loginVo);
    }
    @PostMapping("/social/login")
    public R<?> socialLogin(@RequestBody JSONObject body) {
        String code = body.getString("code");
        if(StringUtils.isEmpty(code)){
            return R.fail("code为空");
        }
//        String ip = dictService.getDictValue("phy_social_ip", "蓝鸽系统IP", "000000");
        LambdaQueryWrapper<SysDictData> queryWrapper=new LambdaQueryWrapper<SysDictData>();
        queryWrapper.select(SysDictData::getDictLabel);
        queryWrapper.eq(SysDictData::getDictType, "phy_social_ip");
        queryWrapper.eq(SysDictData::getDictLabel, "蓝鸽系统IP");
        queryWrapper.eq(SysDictData::getTenantId,"000000");
        SysDictData sysDictData = sysDictDataMapper.selectOne(queryWrapper);
        String ip=sysDictData!=null?sysDictData.getDictValue():"192.168.41.10:20000";
        if(StringUtils.isEmpty(ip)){
            ip="192.168.41.10:20000";
        }
        String parentUrl="http://"+ip+"/BaseApi/OAuth";
//        String url="https://apifoxmock.com/m1/4854226-4509697-default/BaseApi/OAuth/GetTokenByCode?appid=0250672971&grant_type=authriztion_code&client_secret=1D1BCC675B404CE075CC4288&code=7106b6f8fe4f49e99ab23f5df5f0b3fc";
        String url=parentUrl+"/GetTokenByCode?appid=0250672971&grant_type=authriztion_code&client_secret=1D1BCC675B404CE075CC4288&code="+code;
        SendToServer sendToServer=new SendToServer();
        sendToServer.setUrl(url);
        sendToServer.setMethod("POST");
        String s = synchronizeImageService.sendGetOrPostRequest(sendToServer);
        if("1".equals(s)){
            return R.fail("请求超时");
        }
        JSONObject jsonObject =JSONObject.parseObject(s);
        Long statusCode = jsonObject.getLong("StatusCode");
        if(statusCode!=200){
            log.info("第三方登录异常-获取第三方用户信息:  "+s);
            return R.fail("登录失败");
        }
        JSONObject data = jsonObject.getJSONObject("Data");
        String openid = data.getString("openid");
        String accessToken = data.getString("access_token");
        if(StringUtils.isEmpty(openid)||StringUtils.isEmpty(accessToken)){
            return R.fail("登录失败");
        }
//        url="https://apifoxmock.com/m1/4854226-4509697-default/BaseApi/OAuth/GetUserInfo?openid=d1db3c9d-f1c0-432b-932a-91884909281a";
        url=parentUrl+"/GetUserInfo?openid="+openid;
        sendToServer.setUrl(url);
        sendToServer.setMethod("GET");
        sendToServer.setAuthorization("Bearer "+accessToken);
        String result = synchronizeImageService.sendGetOrPostRequest(sendToServer);
        if("1".equals(result)){

            return R.fail("登录失败");
        }

        JSONObject getUser =JSONObject.parseObject(result);
        Long statusCode1 = getUser.getLong("StatusCode");
        if(statusCode1!=200){
            log.info("第三方登录异常:  "+result);
            return R.fail("登录失败");
        }
        JSONObject data1 = getUser.getJSONObject("Data");
        SysSocialUserBo javaObject1 = data1.toJavaObject(SysSocialUserBo.class);


        if(ObjectUtil.isNull(javaObject1)){
            return R.fail("登录失败");
        }
        SysSocialUser javaObject =new SysSocialUser();
        if(StringUtils.isEmpty(javaObject1.getOpenid())||StringUtils.isEmpty(javaObject1.getUser_id())){
            return R.fail("登录失败");
        }
        javaObject.setOpenid(javaObject1.getOpenid());
        javaObject.setUserId(javaObject1.getUser_id());
        javaObject.setUserType(javaObject1.getUser_type());
        javaObject.setUserName(javaObject1.getUser_name());
        LambdaQueryWrapper<SysSocialUser> queryWrapper1=new LambdaQueryWrapper<>();
        queryWrapper1.eq(SysSocialUser::getOpenid,javaObject.getOpenid());
        queryWrapper1.eq(SysSocialUser::getTenantId,"000000");

        SysSocialUser sysSocialUser = sysSocialUserMapper.selectOne(queryWrapper1);
        boolean b1;
        if(sysSocialUser!=null){
            b1 = sysSocialUserMapper.updateById(javaObject)>0;
        }else {
            javaObject.setTenantId("000000");
            b1 = sysSocialUserMapper.insert(javaObject)>0;
        }
        if(!b1){
            log.info("第三方登录异常-创建第三方信息表:  "+javaObject);
            return R.fail("登录失败");
        }

        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper=new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(SysUser::getTenantId,"000000");
        sysUserLambdaQueryWrapper.eq(SysUser::getDelFlag,"0");
        if(sysSocialUser==null){
            sysUserLambdaQueryWrapper.eq(SysUser::getUserName,javaObject.getUserId());
        }else {
            sysUserLambdaQueryWrapper.eq(SysUser::getUserName,sysSocialUser.getUserId());
        }
        SysUser sysUser1 = userMapper.selectOne(sysUserLambdaQueryWrapper);
        System.out.println("sysUser1"+sysUser1);
        SysUser sysUser=new SysUser();
        sysUser.setNickName(javaObject.getUserName());
        sysUser.setUserName(javaObject.getUserId());
        sysUser.setTenantId("000000");
        sysUser.setUserType("sys_user");
        sysUser.setPassword(BCrypt.hashpw(javaObject.getUserId()));
        if(sysUser1==null){

            boolean insert1 = userMapper.insert(sysUser)>0;
            if(!insert1){
                log.info("第三方登录异常-创建用户失败:  "+sysUser);
                return R.fail("登录失败");
            }
            LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper=new LambdaQueryWrapper<>();
            sysRoleLambdaQueryWrapper.eq(SysRole::getRoleKey, "social");
            sysRoleLambdaQueryWrapper.eq(SysRole::getTenantId,"000000");
            SysRole sysRole = sysRoleMapper.selectOne(sysRoleLambdaQueryWrapper);
            if(sysRole!=null){
                SysUserRole ur = new SysUserRole();
                ur.setUserId(sysUser.getUserId());
                ur.setRoleId(sysRole.getRoleId());
                userRoleMapper.insert(ur);
            }
//            userRoleMapper.delete(new LambdaQueryWrapper<SysUserRole>().eq(SysUserRole::getUserId, sysUser.getUserId()));
        }
        else {
            sysUser.setUserId(sysUser1.getUserId());
            LambdaQueryWrapper<SysUser> userLambdaQueryWrapper=new LambdaQueryWrapper<>();
            userLambdaQueryWrapper.eq(SysUser::getTenantId,"000000");
            userLambdaQueryWrapper.eq(SysUser::getUserId,sysUser1.getUserId());
            boolean b = userMapper.updateUserForSocial(sysUser) > 0;
            if(!b){
                log.info("第三方登录异常-更新用户失败:  "+sysUser);
                return R.fail("登录失败");
            }
        }
        String grantType = "password";
        SysClient client = clientService.queryByClientId("e5cd7e4891bf95d1d19206ce24a7b32e");
        // 登录
        LoginVo loginVo = IAuthStrategy.socialLogin(javaObject.getUserId(), "000000",client,grantType);

        Long userId = LoginHelper.getUserId();

        scheduledExecutorService.schedule(() -> {
            WebSocketUtils.sendMessage(userId, "欢迎登录RuoYi-Vue-Plus后台管理系统");
        }, 3, TimeUnit.SECONDS);
        return R.ok(loginVo);
    }
    @GetMapping(value = "/ls/config/")
    public R<String> getConfigKey() {
        String configKey="phy.social.login";
        return R.ok("操作成功", configService.selectConfigByKey(configKey));
    }



}
